--- title: "03-RAG 检索增强生成" created: 2026-08-31 tags: - 项目筑基 --- # RAG 检索增强生成 > 前两篇是"检索"侧的原理,这一篇把 RAG 全流程串起来——这是向量数据库目前最大的应用场景。附一个照官方文档写的最小可跑示例(**我没有实际跑过,跑的时候按报错修**)。 ## RAG 到底在解决什么问题 大模型两个硬伤:**知识有截止日期**、**没见过你的私有数据**;硬问它就编(幻觉)。RAG 的思路很朴素:**回答之前,先去向量库里把相关资料检索出来,塞进 prompt 让模型"开卷考试"**。 好处:知识随时可更新(重新入库即可)、答案可溯源(能给引用)、私有数据不出库。 ## 完整流水线 ``` 离线入库:加载文档 → 清洗 → 切块 → embedding 模型转向量 → 存入向量库(元数据一起存) 在线查询:用户提问 → 同一模型转向量 → ANN 检索 top K → (rerank 精排) → 拼进 prompt → LLM 生成答案 ``` 对应到工程组件:**加载/切块**用 LangChain 的 splitter 或自己写;**embedding** 用 bge 系或 API;**向量库**按概览篇的选型直觉(学习用 Chroma);**编排** LangChain / LlamaIndex,或干脆手写——书里的观点是:**最小 RAG 手写百来行就够,先跑通再上框架**,框架的黑盒会掩盖原理。 ## 最小可跑示例(照官方文档写的,未实测) 目标:Chroma(内嵌模式,零部署)+ bge 中文模型,存三条笔记然后按语义检索。 ```bash pip install chromadb sentence-transformers ``` ```python from chromadb import PersistentClient from sentence_transformers import SentenceTransformer # bge 中文模型,首次运行会自动下载(约 1.3GB) model = SentenceTransformer("BAAI/bge-large-zh-v1.5") # 内嵌模式:数据落在本地目录,零部署;持久化后重启可读回 client = PersistentClient(path="./chroma_data") # 建集合:显式指定余弦度量(Chroma 默认 L2,归一化向量下两者等价,但显式更稳) col = client.get_or_create_collection("notes", metadata={"hnsw:space": "cosine"}) docs = [ "SQLite 的 WAL 模式解决 database is locked 问题", "Redis 的 SET 命令加 NX 和 EX 可以做简易分布式锁", "MySQL 的 InnoDB 用 B+ 树组织索引", ] emb = model.encode(docs, normalize_embeddings=True) col.add(ids=["n1", "n2", "n3"], embeddings=emb.tolist(), documents=docs) # 查询:语义找,字面完全不同也能命中 q = model.encode(["redis 怎么实现锁"], normalize_embeddings=True) res = col.query(query_embeddings=q.tolist(), n_results=2) print(res["ids"], res["documents"]) # 期望 n2 排第一 ``` 我标注过的两个核对点:①Chroma 新版 API 建集合的参数写法有变动,以当时官方文档为准;②模型首次下载需要网络,离线环境要提前缓存。 ## 检索不准的排查清单(书里观点的汇总) 效果差时按顺序查,**从数据侧往参数侧**: 1. **切块**:是不是把主题切碎了/块太大稀释了语义?(最大嫌疑,回 02 篇) 2. **模型域匹配**:query 和文档是否同一模型?中文场景有没有用中文榜上像样的模型?bge 的指令前缀加了没? 3. **度量与归一化**:建库时的度量方式、向量有没有归一化、是否不同批次模型混库 4. **检索参数**:top_K 给多少(先 50 再 rerank 到 5)、ef_search/nprobe 是否给得太小 5. **query 本身**:口语化问句是否需要改写(把"这玩意咋弄"改写成关键词式)——进阶做法叫 query rewriting 还有一个反直觉的忠告:**库查不到就拒答**,比检索分数垫底还硬塞给模型编答案强——给检索结果设个相似度阈值,低于阈值直接回"资料里没有"。 ## 进阶名词速记(知道是什么,不展开) - **混合检索**:BM25 关键词检索 + 向量语义检索各跑一路,RRF 融合——专有名词、型号、代码类查询关键词路线反而强 - **父子块**:小块检索、大块喂模型(02 篇提过) - **GraphRAG**:把实体关系抽成图谱再检索,适合"多跳关联"的问题——名词先记着 - **评估**:构造一组"问题 → 期望命中的文档"测试集,算命中率(hit rate)和 MRR——朴素起步够用,别上来就上 RAGAS --- ⬅️ [[02-Embedding 模型与文本切块|02-Embedding 模型与文本切块]] 🏠 [[00-数据库|00-数据库]] ➡️ [[Alembic|Alembic]]